/*
 * Copyright 2019-2025 the original author or authors.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * https://www.apache.org/licenses/LICENSE-2.0
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.iiifi.kite.ribbon.rule;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import org.springframework.cloud.commons.util.InetUtils;
import org.springframework.util.PatternMatchUtils;

import com.alibaba.cloud.nacos.ribbon.NacosServer;
import com.iiifi.kite.core.spring.SpringContextUtils;
import com.iiifi.kite.core.util.ObjectUtils;
import com.iiifi.kite.configuration.KiteProperties;
import com.iiifi.kite.ribbon.KiteRibbonProperties;
import com.iiifi.kite.ribbon.predicate.MetadataAwarePredicate;
import com.netflix.loadbalancer.Server;

/**
 * ribbon 路由规则器
 *
 * @author kite@iiifi.com 花朝
 */
public class MetadataAwareRule extends DiscoveryEnabledRule {

    public static final String IS_LOCAL = "is-local";

    public MetadataAwareRule() {
        super(MetadataAwarePredicate.INSTANCE);
    }

    @Override
    public List<Server> filterServers(List<Server> serverList) {
        InetUtils inetUtils = SpringContextUtils.getBean(InetUtils.class);
        KiteProperties kiteProperties = SpringContextUtils.getBean(KiteProperties.class);
        KiteRibbonProperties kiteRibbonProperties = SpringContextUtils.getBean(KiteRibbonProperties.class);
        // 配置有问题时不进行路由策略调整
        if (inetUtils == null || kiteProperties == null || kiteRibbonProperties == null) {
            return serverList;
        }
        List<String> priorIpPattern = kiteRibbonProperties.getPriorIpPattern();
        // 1. 查找是否有本机 ip
        String hostIp = inetUtils.findFirstNonLoopbackHostInfo().getIpAddress();

        // 优先的 ip 规则
        boolean hasPriorIpPattern = !priorIpPattern.isEmpty();
        String[] priorIpPatterns = priorIpPattern.toArray(new String[0]);

        List<Server> priorServerList = new ArrayList<>();
        for (Server server : serverList) {
            if (server instanceof NacosServer) {
                // 如果当前服务器不是本地服务,不允许路由到开发机服务
                if (!kiteProperties.getIsLocal()
                        && Boolean.parseBoolean(((NacosServer) server).getMetadata().get(IS_LOCAL))) {
                    continue;
                }
            }
            String host = server.getHost();
            // 2. 优先本地 ip 的服务
            if (ObjectUtils.nullSafeEquals(hostIp, host) && kiteProperties.getIsLocal()) {
                return Collections.singletonList(server);
            }
            // 3. 优先的 ip 服务
            if (hasPriorIpPattern && PatternMatchUtils.simpleMatch(priorIpPatterns, host)) {
                priorServerList.add(server);
            }
        }

        // 4. 如果优先的有数据直接返回
        if (!priorServerList.isEmpty()) {
            return priorServerList;
        }

        return Collections.unmodifiableList(serverList);
    }

}
